/**
 * @description: 墙面几何体
 * @param {*} path 墙面路径: [[0, 0], [1, 0], ...]、[[0, 0, 1], [1, 0, 2], ...]
 * @param {*} height 墙面高度: 二维path必须设置高度; 三维path可选，如果设置了将作为基础高度;
 * @return {*}
 */
export default class WallGeometry {
  constructor(path, height) {
    const _path = path.map((p) => {
      const v = [...p];

      if (v.length === 2) {
        v.push(height ?? 1);
      } else if (v.length === 3) {
        v[2] += height ?? 0;
      }

      return v;
    });

    const geometry = new THREE.BufferGeometry();

    const vertices = [];
    const curvePath = new THREE.CurvePath();

    for (let i = 0, len = _path.length; i < len - 1; i++) {
      const [x1, y1, z1] = _path[i];
      const [x2, y2, z2] = _path[i + 1];
      const lt = [x1, y1, z1];
      const lb = [x1, y1, 0];
      const rt = [x2, y2, z2];
      const rb = [x2, y2, 0];

      vertices.push(...lt, ...lb, ...rt, ...lb, ...rb, ...rt);
      curvePath.add(new THREE.LineCurve3(new THREE.Vector3(...lb), new THREE.Vector3(...rb)));
    }

    const position = new THREE.Float32BufferAttribute(vertices, 3);
    geometry.setAttribute('position', position);
    geometry.computeVertexNormals();

    const uvs = [];
    const lengths = curvePath.getCurveLengths();
    const length = lengths.reduce((a, b) => a + b);
    const maxHeight = Math.max(..._path.map((v) => v[2]));
    let curLength = 0;

    for (let i = 0, len = lengths.length; i < len; i++) {
      const sr = curLength / length;
      const er = (curLength + lengths[i]) / length;
      const sz = _path[i][2] / maxHeight;
      const ez = _path[i + 1][2] / maxHeight;

      curLength += lengths[i];
      uvs.push(sr, sz, sr, 0, er, ez, sr, 0, er, 0, er, ez);
    }

    const uv = new THREE.Float32BufferAttribute(uvs, 2);
    geometry.setAttribute('uv', uv);

    return geometry;
  }
}
